home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / rw / readWriteXWD.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  15KB  |  629 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1993, David Koblas (koblas@netcom.com)                  | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. /* 
  16. **
  17. ** Copyright (C) 1989, 1991 by Jef Poskanzer.
  18. **
  19. ** Permission to use, copy, modify, and distribute this software and its
  20. ** documentation for any purpose and without fee is hereby granted, provided
  21. ** that the above copyright notice appear in all copies and that both that
  22. ** copyright notice and this permission notice appear in supporting
  23. ** documentation.  This software is provided "as is" without express or
  24. ** implied warranty.
  25. */
  26.  
  27.  
  28. #include "image.h"
  29. #include <stdio.h>
  30.  
  31. #include <X11/XWDFile.h>
  32.  
  33. /*
  34. **  Some version of XWDFile.h don't have the 'typedef' infront of
  35. **    the XWDColor definition.
  36. */
  37. typedef struct {
  38.         CARD32  pixel B32;
  39.         CARD16  red B16;
  40.         CARD16  green B16;
  41.         CARD16  blue B16;
  42.         CARD8   flags;
  43.         CARD8   pad;
  44. } myXWDColor;
  45.  
  46. #define XWDColor    myXWDColor
  47.  
  48.  
  49. void *calloc(int, int);
  50.  
  51. #define True    1
  52. #define False    0
  53.  
  54. #define LSBFirst    0
  55. #define MSBFirst    1
  56.  
  57. #define XYBitmap    0
  58. #define XYPixmap    1
  59. #define ZPixmap        2
  60.  
  61. #define StaticGray    0
  62. #define GrayScale    1
  63. #define StaticColor    2
  64. #define PseudoColor    3
  65. #define TrueColor    4
  66. #define DirectColor    5
  67.  
  68. #if XWD_FILE_VERSION != 7
  69. *** This is an error ***
  70.  
  71. Do not know how to write anything but version 7 X window dumps
  72.  
  73. #endif
  74.  
  75. /*
  76. **  Some read and write routines for long values
  77. */
  78.  
  79. static unsigned long readlong(FILE *fp)
  80. {
  81.     unsigned char    a, b, c, d;
  82.  
  83.     a = getc(fp);
  84.     b = getc(fp);
  85.     c = getc(fp);
  86.     d = getc(fp);
  87.  
  88.     return ((a & 0xff) << 24) |
  89.            ((b & 0xff) << 16) |
  90.            ((c & 0xff) <<  8) |
  91.             (d & 0xff);
  92. }
  93. static unsigned short readshort(FILE *fp)
  94. {
  95.     unsigned char    a, b;
  96.     a = getc(fp);
  97.     b = getc(fp);
  98.  
  99.     return ((a & 0xff) << 8) | (b & 0xff);
  100. }
  101.  
  102. static void writelong(FILE *fp, long l)
  103. {
  104.     putc( (l >> 24) & 0xff, fp);
  105.     putc( (l >> 16) & 0xff, fp);
  106.     putc( (l >>  8) & 0xff, fp);
  107.     putc(  l        & 0xff, fp);
  108. }
  109. static void writeshort(FILE *fp, unsigned short s)
  110. {
  111.     putc( (s >>  8) & 0xff, fp);
  112.     putc(  s        & 0xff, fp);
  113. }
  114.  
  115. static long swaplong(long l)
  116. {
  117.     unsigned char    b1, b2, b3, b4;
  118.  
  119.     b1 = (l >> 24) & 0xff;
  120.     b2 = (l >> 16) & 0xff;
  121.     b3 = (l >>  8) & 0xff;
  122.     b4 =  l        & 0xff;
  123.  
  124.     return ((long)b4 << 24) | ((long)b3 << 16) | (b2 << 8) | b1;
  125. }
  126. static short swapshort(short l)
  127. {
  128.     unsigned char    b1, b2;
  129.  
  130.     b1 = (l >>  8) & 0xff;
  131.     b2 =  l        & 0xff;
  132.  
  133.     return (b2 << 8) | b1;
  134. }
  135.  
  136. /*
  137. **
  138. */
  139. static int         bits_per_item, bits_used, bit_shift, bits_per_pixel;
  140. static unsigned long     pixel_mask;
  141. static int         byte_order, bit_order;
  142.  
  143.  
  144. static unsigned long getpixnum(FILE *fp)
  145. {
  146.     static unsigned char    b8;
  147.     static unsigned short    b16;
  148.     static unsigned long    b32;
  149.     unsigned long         val;
  150.  
  151.     if (bits_used == bits_per_item ) {
  152.         switch (bits_per_item) {
  153.         case 8:
  154.             b8 = getc(fp);
  155.             break;
  156.         case 16:
  157.             b16 = readshort(fp);
  158.             if (byte_order != MSBFirst)
  159.                 b16 = swapshort(b16);
  160.             break;
  161.         case 32:
  162.             b32 = readlong(fp);
  163.             if (byte_order != MSBFirst)
  164.                 b32 = swaplong(b32);
  165.             break;
  166.         }
  167.         bits_used = 0;
  168.  
  169.         if (bit_order == MSBFirst)
  170.             bit_shift = bits_per_item - bits_per_pixel;
  171.         else
  172.             bit_shift = 0;
  173.     }
  174.  
  175.     switch (bits_per_item) {
  176.     case 8:
  177.         val = (b8 >> bit_shift) & pixel_mask;
  178.         break;
  179.     case 16:
  180.         val = (b16 >> bit_shift) & pixel_mask;
  181.         break;
  182.     case 32:
  183.         val = (b32 >> bit_shift) & pixel_mask;
  184.         break;
  185.     }
  186.  
  187.     if (bit_order == MSBFirst)
  188.         bit_shift -= bits_per_pixel;
  189.     else
  190.         bit_shift += bits_per_pixel;
  191.     bits_used += bits_per_pixel;
  192.  
  193.     return val;
  194. }
  195.  
  196.  
  197.  
  198. /*
  199. **  Straight forward writer.
  200. **   Take advantage of the fact that a Grey image is 8 bits deep
  201. **   and some simple properties of colormap images for simplicity.
  202. */
  203. int WriteXWD(char *file, Image *image)
  204. {
  205.     static char    *name = "XPaint Image";
  206.     XWDColor    color;
  207.     XWDFileHeader    hdr;
  208.     FILE        *fp;
  209.     int        i, x, y;
  210.     int        isBW = 0, isGrey = 0;
  211.  
  212.     if ((fp = fopen(file, "w")) == NULL)
  213.         return True;
  214.  
  215.     /* 
  216.     **  Set up the header.
  217.     */
  218.     hdr.header_size = sizeof(hdr) + strlen(name) + 1;
  219.     hdr.file_version = XWD_FILE_VERSION;
  220.     hdr.pixmap_format = ZPixmap;
  221.     hdr.pixmap_width = image->width;
  222.     hdr.pixmap_height = image->height;
  223.     hdr.xoffset = 0;
  224.     hdr.byte_order = MSBFirst;
  225.     hdr.bitmap_bit_order = MSBFirst;
  226.     hdr.window_width = image->width;
  227.     hdr.window_height = image->height;
  228.     hdr.window_x = 0;
  229.     hdr.window_y = 0;
  230.     hdr.window_bdrwidth = 0;
  231.  
  232.     if (image->isBW) {
  233.         hdr.pixmap_depth = 1;
  234.         hdr.bits_per_pixel = 1;
  235.         hdr.colormap_entries = image->cmapSize;
  236.         hdr.ncolors = image->cmapSize;
  237.         hdr.bytes_per_line = ( image->width + 7 ) / 8;
  238.  
  239.         isBW = 1;
  240.  
  241.         /*
  242.         **  Common between grey and BW
  243.         */
  244.         hdr.bitmap_unit = 8;
  245.         hdr.bitmap_pad = 8;
  246.         hdr.visual_class = StaticGray;
  247.         hdr.red_mask = 0;
  248.         hdr.green_mask = 0;
  249.         hdr.blue_mask = 0;
  250.     } else if (image->isGrey) {
  251.         hdr.pixmap_depth = 8;
  252.         hdr.bits_per_pixel = 8;
  253.         hdr.colormap_entries = image->cmapSize;
  254.         hdr.ncolors = image->cmapSize;
  255.         hdr.bytes_per_line = image->width;
  256.  
  257.         isGrey = 1;
  258.  
  259.         /*
  260.         **  Common between grey and BW
  261.         */
  262.         hdr.bitmap_unit = 8;
  263.         hdr.bitmap_pad = 8;
  264.         hdr.visual_class = StaticGray;
  265.         hdr.red_mask = 0;
  266.         hdr.green_mask = 0;
  267.         hdr.blue_mask = 0;
  268.     } else if (image->cmapSize > 0) {
  269.         /*
  270.         **  Color mapped image
  271.         */
  272.         hdr.pixmap_depth = (image->cmapSize > 256) ? 16 : 8;
  273.         hdr.bits_per_pixel = (image->cmapSize > 256) ? 16 : 8;
  274.         hdr.visual_class = PseudoColor;
  275.         hdr.colormap_entries = image->cmapSize;
  276.         hdr.ncolors = image->cmapSize;
  277.         hdr.red_mask = 0;
  278.         hdr.green_mask = 0;
  279.         hdr.blue_mask = 0;
  280.         hdr.bytes_per_line = image->width;
  281.         hdr.bitmap_unit = 8;
  282.         hdr.bitmap_pad = 8;
  283.     } else {
  284.         /*
  285.         **  RGB Image
  286.         */
  287.         hdr.pixmap_depth = 24;
  288.         hdr.bitmap_unit = 32;
  289.         hdr.bitmap_pad = 32;
  290.         hdr.bits_per_pixel = 32;
  291.         hdr.visual_class = DirectColor;
  292.         hdr.colormap_entries = 256;
  293.         hdr.ncolors = 0;
  294.         hdr.red_mask = 0xff0000;
  295.         hdr.green_mask = 0xff00;
  296.         hdr.blue_mask = 0xff;
  297.         hdr.bytes_per_line = image->width * 4;
  298.     }
  299.     hdr.bits_per_rgb = hdr.pixmap_depth;
  300.  
  301.     /* Write out the header in big-endian order. */
  302.     writelong(fp, hdr.header_size );
  303.     writelong(fp, hdr.file_version );
  304.     writelong(fp, hdr.pixmap_format );
  305.     writelong(fp, hdr.pixmap_depth );
  306.     writelong(fp, hdr.pixmap_width );
  307.     writelong(fp, hdr.pixmap_height );
  308.     writelong(fp, hdr.xoffset );
  309.     writelong(fp, hdr.byte_order );
  310.     writelong(fp, hdr.bitmap_unit );
  311.     writelong(fp, hdr.bitmap_bit_order );
  312.     writelong(fp, hdr.bitmap_pad );
  313.     writelong(fp, hdr.bits_per_pixel );
  314.     writelong(fp, hdr.bytes_per_line );
  315.     writelong(fp, hdr.visual_class );
  316.     writelong(fp, hdr.red_mask );
  317.     writelong(fp, hdr.green_mask );
  318.     writelong(fp, hdr.blue_mask );
  319.     writelong(fp, hdr.bits_per_rgb );
  320.     writelong(fp, hdr.colormap_entries );
  321.     writelong(fp, hdr.ncolors );
  322.     writelong(fp, hdr.window_width );
  323.     writelong(fp, hdr.window_height );
  324.     writelong(fp, hdr.window_x );
  325.     writelong(fp, hdr.window_y );
  326.     writelong(fp, hdr.window_bdrwidth );
  327.  
  328.     /* 
  329.     **  Write out the dump name.
  330.     */
  331.     fwrite(name, 1, strlen(name) + 1, fp);
  332.  
  333.     /* 
  334.     **   Write out the colormap, big-endian order.
  335.     */
  336.     color.flags = 7;
  337.     color.pad = 0;
  338.     for ( i = 0; i < image->cmapSize; ++i ) {
  339.         color.pixel = i;
  340.  
  341.         if (isBW) {
  342.             color.red   = i * 65535L;
  343.             color.green = color.red;
  344.             color.blue  = color.red;
  345.         } else if (isGrey) {
  346.             color.red   = i << 8;
  347.             color.green = color.red;
  348.             color.blue  = color.red;
  349.         } else {
  350.             color.red   = image->cmapData[i * 3 + 0] << 8;
  351.             color.green = image->cmapData[i * 3 + 1] << 8;
  352.             color.blue  = image->cmapData[i * 3 + 2] << 8;
  353.         }
  354.         writelong( fp, color.pixel );
  355.         writeshort( fp, color.red );
  356.         writeshort( fp, color.green );
  357.         writeshort( fp, color.blue );
  358.         (void)putc( color.flags, fp );
  359.         (void)putc( color.pad, fp );
  360.     }
  361.  
  362.     /* 
  363.     ** Finally, write out the data.
  364.     */
  365.     for (y = 0; y < image->height; y++) {
  366.         if (image->cmapSize == 0) {
  367.             /*
  368.             **  Write RGB Image
  369.             */
  370.             unsigned char    *dp = &image->data[y * image->width * 3];
  371.             for (x = 0; x < image->width; x++) {
  372.                 putc(0, fp);
  373.                 putc(*dp, fp); dp++;
  374.                 putc(*dp, fp); dp++;
  375.                 putc(*dp, fp); dp++;
  376.             }
  377.         } else if (isBW) {
  378.             /*
  379.             **  Write a B&W Image, which is 1 bit per pixel.
  380.             */
  381.             unsigned char    *dp = &image->data[y * image->width];
  382.             int        v = 0, idx = 7;
  383.             for (x = 0; x < image->width; x++, dp++) {
  384.                 v |= *dp << idx;
  385.                 if (--idx < 0) {
  386.                     idx = 7;
  387.                     putc(v & 0xff, fp);
  388.                     v = 0;
  389.                 }
  390.             }
  391.             if (idx != 7) 
  392.                 putc(v & 0xff, fp);
  393.         } else if (image->cmapSize > 256) {
  394.             /*
  395.             **  Write wide colormapped image
  396.             */
  397.             unsigned short    *dp = &((unsigned short *)image->data)[y * image->width];
  398.             for (x = 0; x < image->width; x++, dp++)
  399.                 writeshort(fp, *dp);
  400.         } else {
  401.             /*
  402.             **  Write normal colormapped image, which is also a Grey image
  403.             */
  404.             unsigned char    *dp = &image->data[y * image->width];
  405.             for (x = 0; x < image->width; x++, dp++)
  406.                 putc(*dp, fp);
  407.         }
  408.     }
  409.  
  410.     fclose(fp);
  411.  
  412.     return False;
  413. }
  414.  
  415. int TestXWD(char *file)
  416. {
  417.     FILE    *fd = fopen(file, "r");
  418.     long    v;
  419.  
  420.     if (fd == NULL)
  421.         return False;
  422.  
  423.     readlong(fd);
  424.     v = readlong(fd);
  425.  
  426.     fclose(fd);
  427.  
  428.     return v == XWD_FILE_VERSION;
  429. }
  430.  
  431. Image *ReadXWD(char *file)
  432. {
  433.     int            isGrey = True, isBW = False;
  434.     FILE            *fp;
  435.     XWDFileHeader        hdr;
  436.     Image            *image = NULL;
  437.     unsigned char        *ibp;
  438.     unsigned short        *isp;
  439.     int            i, x, y;
  440.     unsigned long         red_mask, green_mask, blue_mask;
  441.     int            byte_swap = False;
  442.     int            scale, padright;
  443.  
  444.     if ((fp = fopen(file, "r")) == NULL)
  445.         return NULL;
  446.  
  447.     if (fread(&hdr, sizeof(hdr), 1, fp) != 1) {
  448.         fclose(fp);
  449.         return NULL;
  450.     }
  451.  
  452.     if (swaplong(hdr.file_version) == XWD_FILE_VERSION) {
  453.         byte_swap = True;
  454.         hdr.header_size = swaplong( hdr.header_size );
  455.         hdr.file_version = swaplong( hdr.file_version );
  456.         hdr.pixmap_format = swaplong( hdr.pixmap_format );
  457.         hdr.pixmap_depth = swaplong( hdr.pixmap_depth );
  458.         hdr.pixmap_width = swaplong( hdr.pixmap_width );
  459.         hdr.pixmap_height = swaplong( hdr.pixmap_height );
  460.         hdr.xoffset = swaplong( hdr.xoffset );
  461.         hdr.byte_order = swaplong( hdr.byte_order );
  462.         hdr.bitmap_unit = swaplong( hdr.bitmap_unit );
  463.         hdr.bitmap_bit_order = swaplong( hdr.bitmap_bit_order );
  464.         hdr.bitmap_pad = swaplong( hdr.bitmap_pad );
  465.         hdr.bits_per_pixel = swaplong( hdr.bits_per_pixel );
  466.         hdr.bytes_per_line = swaplong( hdr.bytes_per_line );
  467.         hdr.visual_class = swaplong( hdr.visual_class );
  468.         hdr.red_mask = swaplong( hdr.red_mask );
  469.         hdr.green_mask = swaplong( hdr.green_mask );
  470.         hdr.blue_mask = swaplong( hdr.blue_mask );
  471.         hdr.bits_per_rgb = swaplong( hdr.bits_per_rgb );
  472.         hdr.colormap_entries = swaplong( hdr.colormap_entries );
  473.         hdr.ncolors = swaplong( hdr.ncolors );
  474.         hdr.window_width = swaplong( hdr.window_width );
  475.         hdr.window_height = swaplong( hdr.window_height );
  476.         hdr.window_x = swaplong( hdr.window_x );
  477.         hdr.window_y = swaplong( hdr.window_y );
  478.         hdr.window_bdrwidth = swaplong( hdr.window_bdrwidth );
  479.     } else if (hdr.file_version != XWD_FILE_VERSION) {
  480.         goto out;
  481.     }
  482.  
  483.     /*
  484.     **  Skip stored name
  485.     */
  486.     for (i = 0; i < hdr.header_size - sizeof(hdr); ++i)
  487.         if (getc(fp) == EOF) 
  488.             goto out;
  489.  
  490.     /* Check whether we can handle this dump. */
  491.     if (hdr.pixmap_depth > 24)
  492.         goto out;
  493.     if (hdr.bits_per_rgb > 24) 
  494.         goto out;
  495.     if (hdr.pixmap_format != ZPixmap && hdr.pixmap_depth != 1)
  496.         goto out;
  497.     if (hdr.bitmap_unit != 8 && hdr.bitmap_unit != 16 && hdr.bitmap_unit != 32)
  498.         goto out;
  499.  
  500.     if (hdr.ncolors > 0) {
  501.         XWDColor    *colors;
  502.  
  503.         if ((colors = (XWDColor*)calloc(sizeof(XWDColor), hdr.ncolors)) == NULL)
  504.             goto out;
  505.         if (fread(colors, sizeof(XWDColor), hdr.ncolors, fp) != hdr.ncolors)
  506.             goto out;
  507.  
  508.         image = ImageNewCmap(hdr.pixmap_width, hdr.pixmap_height, hdr.ncolors);
  509.  
  510.         for (i = 0; i < hdr.ncolors; i++) {
  511.             unsigned char    r, g, b;
  512.             if (byte_swap) {
  513.                 colors[i].red = swapshort(colors[i].red);
  514.                 colors[i].green = swapshort(colors[i].green);
  515.                 colors[i].blue = swapshort(colors[i].blue);
  516.             }
  517.             r = colors[i].red >> 8;
  518.             g = colors[i].green >> 8;
  519.             b = colors[i].blue >> 8;
  520.             ImageSetCmap(image, i, r, g, b);
  521.  
  522.             if (r != g || g != b)
  523.                 isGrey = False;
  524.         }
  525.  
  526.         if (isGrey && image->cmapData[0] == 0 && image->cmapData[3] == 255)
  527.                 isBW = True;
  528.     } else {
  529.         /*
  530.         **  RGB Image
  531.         */
  532.         isGrey = False;
  533.     }
  534.  
  535.     if (hdr.visual_class == TrueColor || hdr.visual_class == DirectColor) {
  536.     } else if (hdr.visual_class == StaticGray && hdr.bits_per_pixel == 1) {
  537.         /*
  538.         **  B&W bitmap
  539.         */
  540.     } else if (hdr.visual_class == StaticGray) {
  541.     }
  542.  
  543.     switch (hdr.visual_class) {
  544.     case TrueColor:
  545.     case DirectColor:
  546.         image = ImageNew(hdr.pixmap_width, hdr.pixmap_height);
  547.         if (hdr.bits_per_pixel == 16)
  548.             scale = 4;
  549.         else
  550.             scale = 1;
  551.         break;
  552.     case StaticGray:
  553.         if (image != NULL)
  554.             break;
  555.         if (hdr.bits_per_pixel == 1) {
  556.             image = ImageNewBW(hdr.pixmap_width, hdr.pixmap_height);
  557.         } else {
  558.             image = ImageNewGrey(hdr.pixmap_width, hdr.pixmap_height);
  559.             scale = 256 / (1 << hdr.bits_per_pixel) - 1;
  560.         }
  561.         break;
  562.     default:    /* StaticColor, PseudoColor, GrayScale */
  563.         if (image != NULL)
  564.             break;
  565.         image = ImageNew(hdr.pixmap_width, hdr.pixmap_height);
  566.         break;
  567.     }
  568.  
  569.     padright = hdr.bytes_per_line * 8 / hdr.bits_per_pixel - hdr.pixmap_width;
  570.  
  571.     bits_per_item = hdr.bitmap_unit;
  572.     bits_used     = bits_per_item;
  573.     bits_per_pixel= hdr.bits_per_pixel;
  574.     byte_order    = hdr.byte_order;
  575.     bit_order     = hdr.bitmap_bit_order;
  576.     if ( bits_per_pixel == sizeof(pixel_mask) * 8 )
  577.         pixel_mask = -1;
  578.     else
  579.         pixel_mask = ( 1 << bits_per_pixel ) - 1;
  580.         red_mask   = hdr.red_mask;
  581.         green_mask = hdr.green_mask;
  582.         blue_mask  = hdr.blue_mask;
  583.  
  584.     ibp = image->data;
  585.     isp = (unsigned short *)image->data;
  586.     for (y = 0; y < image->height; y++) {
  587.         switch (hdr.visual_class) {
  588.         case StaticGray:
  589.         case GrayScale:
  590.         case StaticColor:
  591.         case PseudoColor:
  592.             for (x = 0; x < image->width; x++) {
  593.                 if (image->cmapSize > 256)
  594.                     *isp++ = getpixnum(fp);
  595.                 else if (image->isBW == 2)
  596.                     *ibp++ = (getpixnum(fp) == 1) ? 0 : 1;
  597.                 else
  598.                     *ibp++ = getpixnum(fp);
  599.             }
  600.             break;
  601.         case TrueColor:
  602.         case DirectColor:
  603.             for (x = 0; x < image->width; x++) {
  604.                 unsigned long     ul = getpixnum(fp);
  605.                 switch (hdr.bits_per_pixel) {
  606.                 case 16:
  607.                     *ibp++ = (ul & red_mask)   >> 0;
  608.                     *ibp++ = (ul & green_mask) >> 5;
  609.                     *ibp++ = (ul & blue_mask)  >> 10;
  610.                     break;
  611.                 case 24:
  612.                 case 32:
  613.                     *ibp++ = (ul & 0xff0000) >> 16;
  614.                     *ibp++ = (ul & 0x00ff00) >>  8;
  615.                     *ibp++ = (ul & 0x0000ff);
  616.                     break;
  617.                 }
  618.             }
  619.         }
  620.  
  621.         for (x = 0; x < padright; x++)
  622.             getpixnum(fp);
  623.     }
  624.  
  625. out:
  626.     fclose(fp);
  627.     return image;
  628. }
  629.